home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume6 / msdos_mk < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  31.8 KB

  1. Subject:  v06i104:  A Make for MS-DOS and VAX/VMS (msdos_mk)
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.UUCP
  4.  
  5. Submitted by: ihnp4!killer!root
  6. Mod.sources: Volume 6, Issue 104
  7. Archive-name: msdos_mk
  8.  
  9. [  This is so far different from the "standard" make, that it probably
  10.    does not make sense to try to port it, although such a job looks
  11.    to be fairly straightforward.  Some of the ideas contained in this
  12.    program might be interesting to other make fanciers besides myself.
  13.    The manpage is, alas, "nroff output." --r$  ]
  14.  
  15. #!/bin/sh
  16. # This is a shell archive.  Remove anything before this line,
  17. # then unpack it by saving it in a file and typing "sh file".
  18. # Contents:  cmake.bat file.c macro.c make.bat make.c make.h make.man
  19. #    makefile osdate.asm parsedir.c readme token.c
  20.  
  21. echo x - cmake.bat
  22. sed 's/^XX//' > "cmake.bat" <<'@//E*O*F cmake.bat//'
  23. XXlc -ms -ie:\lc\ make
  24. XXlc -ms -ie:\lc\ macro
  25. XXlc -ms -ie:\lc\ token
  26. XXlc -ms -ie:\lc\ parsedir
  27. XXlc -ms -ie:\lc\ file
  28. XXmasm osdate;
  29. XXlink \lc\s\c make macro token parsedir file osdate,make,nul,\lc\s\lc
  30. @//E*O*F cmake.bat//
  31. chmod u=rw,g=r,o= cmake.bat
  32.  
  33. echo x - file.c
  34. sed 's/^XX//' > "file.c" <<'@//E*O*F file.c//'
  35. XX#include <stdio.h>
  36. XX#include "make.h"
  37.  
  38.  
  39. XX/*
  40. XX * Return file-node for 'fname'.
  41. XX * If it doesn't exist, then create one.
  42. XX */
  43. XXFILENODE *filenode(fname)
  44. XXchar *fname;
  45. XX{
  46. XX    FILENODE *f, *afnode(), *gfile();
  47.  
  48. XX    if((f = gfile(fname)) == NULL)
  49. XX        f = afnode(fname);
  50. XX    return f;
  51. XX}
  52.  
  53.  
  54. XX/*
  55. XX * Add a dependency to the node 'fnd'.
  56. XX * 'fnd' will depend on 'fname'.
  57. XX */
  58. XXaddfile(fnd, fname)
  59. XXFILENODE *fnd;
  60. XXchar *fname;
  61. XX{
  62. XX    NODE *n;
  63. XX    FILENODE *f;
  64.  
  65. XX    if(fnd == NULL)            /* punt if no root file */
  66. XX    {
  67. XX        fprintf(stderr, "No current root, can't add dependency '%s'\n", 
  68. XXfname);
  69. XX        return;
  70. XX    }
  71.  
  72. XX    f = filenode(fname);
  73. XX    if((n = (NODE *)malloc(sizeof(NODE))) == NULL) allerr();
  74. XX    n->nnext = fnd->fnode;
  75. XX    fnd->fnode = n;
  76. XX    n->nfile = f;
  77. XX}
  78.  
  79.  
  80. XX/*
  81. XX * Add a line of method-text to the node 'fnode'.
  82. XX */
  83. XXaddmeth(fnode, methtext)
  84. XXFILENODE *fnode;
  85. XXchar *methtext;
  86. XX{
  87. XX    int len;
  88. XX    char *new;
  89.  
  90. XX    if(fnode == NULL || methtext == NULL) return;
  91.  
  92. XX    len = strlen(methtext) + 2;
  93. XX    if(fnode->fmake == NULL)
  94. XX    {
  95. XX        if((fnode->fmake = (char *)malloc(1)) == NULL) allerr();
  96. XX        *(fnode->fmake) = 0;
  97. XX    }
  98. XX    len += strlen(fnode->fmake);
  99.  
  100. XX/* Lattice C doesn't have 'realloc()', so this kludges around it: */
  101. XX    if((new = (char *)malloc(len)) == NULL) allerr();
  102. XX    strcpy(new, fnode->fmake);
  103. XX    free(fnode->fmake);
  104. XX    fnode->fmake = new;
  105.  
  106. XX    strcat(fnode->fmake, methtext);
  107. XX    len = strlen(fnode->fmake);
  108. XX    if(len && fnode->fmake[len - 1] != '\n')
  109. XX        strcat(fnode->fmake, "\n");
  110. XX}
  111.  
  112.  
  113. XX/*
  114. XX * Get a filenode for the file called 'fn'.
  115. XX * Returns NULL if the node doesn't exist.
  116. XX */
  117. XXFILENODE *gfile(fn)
  118. XXchar *fn;
  119. XX{
  120. XX    FILENODE *f;
  121.  
  122. XX    for(f = froot; f != NULL; f = f->fnext)
  123. XX        if(!strcmp(fn, f->fname)) return f;
  124. XX    return NULL;
  125. XX}
  126.  
  127.  
  128. XX/*
  129. XX * Alloc space for a new file node.
  130. XX */
  131. XXFILENODE *afnode(name)
  132. XXchar *name;
  133. XX{
  134. XX    FILENODE *f;
  135.  
  136. XX    for(f=froot; f; f=f->fnext)
  137. XX        if(!strcmp(name, f->fname)) return f;
  138.  
  139. XX    if((f = (FILENODE *)malloc(sizeof(FILENODE))) == NULL) allerr();
  140. XX    if((f->fname = (char *)malloc(strlen(name)+1)) == NULL) allerr();
  141. XX    strcpy(f->fname, name);
  142. XX    f->fmake = NULL;
  143. XX    f->fnode = NULL;
  144. XX    f->fdate = NULL;
  145. XX    f->fflag = 0;
  146.  
  147. XX    f->fnext = froot;
  148. XX    froot = f;
  149. XX    return f;
  150. XX}
  151.  
  152.  
  153. XX/*
  154. XX * Print dependency tree.
  155. XX */
  156. XXprtree()
  157. XX{
  158. XX    FILENODE *f;
  159. XX    NODE *n;
  160.  
  161. XX    for(f = froot; f != NULL; f = f->fnext)
  162. XX    {
  163. XX        printf("%s%s%s (%u, %u)\n",
  164. XX            f->fname,
  165. XX            (f->fflag & ROOTP) ? " (root)" : "",
  166. XX            (f->fflag & REBUILT) ? " (rebuilt)" : "",
  167. XX            (f->fdate != NULL) ? (f->fdate)->ds_high : 0,
  168. XX            (f->fdate != NULL) ? (f->fdate)->ds_low : 0);
  169. XX        if(f->fmake != NULL)
  170. XX            printf("%s", f->fmake);
  171. XX        for(n = f->fnode; n != NULL; n = n->nnext)
  172. XX            printf("\t%s\n", (n->nfile)->fname);
  173. XX        puts("");
  174. XX    }
  175. XX}
  176. @//E*O*F file.c//
  177. chmod u=rw,g=r,o= file.c
  178.  
  179. echo x - macro.c
  180. sed 's/^XX//' > "macro.c" <<'@//E*O*F macro.c//'
  181. XX#include <stdio.h>
  182. XX#include "make.h"
  183.  
  184. XX/*
  185. XX * Macro processing
  186. XX */
  187.  
  188.  
  189. XX/*
  190. XX * Perform macro substitution from 'orig' to 'dest'.
  191. XX * Return number of macro substitutions made.
  192. XX * A macro reference is in one of two forms:
  193. XX *        <MACCHAR>(macro-name)
  194. XX *      or    <MACCHAR><single-character>
  195. XX *
  196. XX * "<MACCHAR><MACCHAR>" expands to a single '<MACCHAR>'
  197. XX */
  198. XXmexpand(orig, dest, destsiz, macchar)
  199. XXchar *orig, *dest;
  200. XXint destsiz;
  201. XXchar macchar;
  202. XX{
  203. XX    char *s, *d, mname[STRSIZ];
  204. XX    int di, count;
  205. XX    MACRO *m;
  206.  
  207. XX    di = count = 0;
  208. XX    for(s=orig; *s;)
  209. XX        if(*s == macchar)
  210. XX        {
  211. XX            if(*++s == macchar)
  212. XX            {
  213. XX                if(di < destsiz-1) dest[di++] = *s++;
  214. XX                continue;
  215. XX            }
  216.  
  217. XX            if(!*s) break;
  218. XX            d = mname;
  219. XX            if(*s != '(') *d++ = *s++;
  220. XX            else
  221. XX            {
  222. XX                for(++s; *s && *s!=')';) *d++ = *s++;
  223. XX                if(*s != ')') puts("Missed matching ')'");
  224. XX                else ++s;
  225. XX            }
  226. XX            *d = 0;
  227. XX            if((d = gmacro(mname)) == NULL)
  228. XX                fprintf(stderr, "Undefined macro: %s\n", mname);
  229. XX            else
  230. XX            {
  231. XX                while(*d && di < (destsiz - 1))
  232. XX                    dest[di++] = *d++;
  233. XX                ++count;
  234. XX            }
  235. XX        } else if(di < destsiz-1)
  236. XX            dest[di++] = *s++;
  237.  
  238. XX    dest[di]=0;
  239. XX    return count;
  240. XX}
  241.  
  242.  
  243. XX/*
  244. XX * Define a macro.
  245. XX * Give the macro called 'name' the string expansion 'def'.
  246. XX * Old macro-names are superseded, NOT replaced.
  247. XX * Return ERROR if can't define the macro.
  248. XX */
  249. XXdefmac(name, def)
  250. XXchar *name, *def;
  251. XX{
  252. XX    MACRO *m;
  253.  
  254. XX    if((m = (MACRO *)malloc(sizeof(MACRO))) == NULL) allerr();
  255. XX    if((m->mname = (char *)malloc(strlen(name)+1)) == NULL) allerr();
  256. XX    if((m->mvalue = (char *)malloc(strlen(def)+1)) == NULL) allerr();
  257.  
  258. XX    strcpy(m->mname, name);
  259. XX    strcpy(m->mvalue, def);
  260. XX    m->mnext = mroot;
  261. XX    mroot = m;
  262. XX}
  263.  
  264.  
  265. XX/*
  266. XX * undefmac - undefine a macro.
  267. XX * Return 0 if macro was succesfully undefined, -1 if not found.
  268. XX */
  269. XXundefmac(name)
  270. XXchar *name;
  271. XX{
  272. XX    MACRO *m = mroot;
  273. XX    MACRO *prev = NULL;
  274.  
  275. XX    while(m != NULL && strcmp(name, m->mname))
  276. XX    {
  277. XX        prev = m;
  278. XX        m = m->mnext;
  279. XX    }
  280.  
  281. XX    if(m == NULL) return -1;
  282. XX    if(prev == NULL) mroot = m->mnext;
  283. XX        else prev->mnext = m->mnext;
  284.  
  285. XX    free(m->mname);
  286. XX    free(m->mvalue);
  287. XX    free(m);
  288. XX    return 0;
  289. XX}
  290.  
  291.  
  292. XX/*
  293. XX * Lookup a macro called 'name'.
  294. XX * Return a pointer to its definition,
  295. XX * or NULL if it does not exist.
  296. XX */
  297. XXchar *gmacro(name)
  298. XXchar *name;
  299. XX{
  300. XX    MACRO *m;
  301.  
  302. XX    for(m=mroot; m != NULL; m=m->mnext)
  303. XX        if(!strcmp(name, m->mname)) return m->mvalue;
  304. XX    return NULL;
  305. XX}
  306. @//E*O*F macro.c//
  307. chmod u=rw,g=r,o= macro.c
  308.  
  309. echo x - make.bat
  310. sed 's/^XX//' > "make.bat" <<'@//E*O*F make.bat//'
  311. XXecho off
  312. XXif exist make$$$$.bat del make$$$$.bat
  313. XXxmake %1 %2 %3 %4 %5 %6 %7 %8 %9
  314. XXif exist make$$$$.bat make$$$$.bat
  315. @//E*O*F make.bat//
  316. chmod u=rw,g=r,o= make.bat
  317.  
  318. echo x - make.c
  319. sed 's/^XX//' > "make.c" <<'@//E*O*F make.c//'
  320. XX#include <stdio.h>
  321. XX#include <ctype.h>
  322. XX#include "make.h"
  323.  
  324. XX/*
  325. XX *    MAKE - Maintain seperate source files
  326. XX *
  327. XX *    SYNOPSIS
  328. XX *        MK [-f file] [-a] [-n] [-d] [name] ...
  329. XX *           f: use 'file' instead of default makefile
  330. XX *           a: assume all modules are obsolete (recompile everything)
  331. XX *           n: don't recompile, just list steps to recompile
  332. XX *           d: debugging (print tree, file info)
  333. XX *           name: module name to recompile
  334. XX *
  335. XX *        'secret' options (not to be used by humans):
  336. XX *           -ofile    'file' is the script file to write to
  337. XX *
  338. XX *    AUTHOR
  339. XX *        Landon M. Dyer, Atari Inc.
  340. XX *
  341. XX */
  342.  
  343. XX#define SCRIPTFILE "make$$$$.bat"    /* (default) script-listing file */
  344. XX#define    INIT    "~INIT"            /* initialization macro */
  345. XX#define    DEINIT    "~DEINIT"        /* de-init macro */
  346. XX#define    BEFORE    "~BEFORE"        /* the per-root 'startup' method */
  347. XX#define    AFTER    "~AFTER"        /* the per-root 'wrapup' method */
  348.  
  349.  
  350. XXchar *mfiles[] = {            /* default makefiles */
  351. XX    "makefile",
  352.  
  353. XX#ifdef VAXVMS
  354. XX    "[-]makefile",
  355. XX    "sys$login:makefile",
  356. XX#endif
  357.  
  358. XX#ifdef MSDOS
  359. XX    "..\makefile",
  360. XX#endif
  361. XX    ""
  362. XX};
  363.  
  364.  
  365. XXMACRO *mroot = NULL;        /* root of macro-list */
  366. XXFILENODE *froot = NULL;        /* root of filenode-list */
  367. XXFILENODE *firstf = NULL;    /* the very first filenode */
  368. XXFILE *mkfp = NULL;        /* script file */
  369. XXchar *modnames[MAXMODS];    /* module-names mentioned in commandline */
  370. XXint modcount = 0;        /* #of module-names */
  371. XXint debug = 0;            /* nonzero: turn on debugging */
  372. XXint obsolete = 0;        /* nonzero: every file should be recompiled */
  373. XXint noscript = 0;        /* nonzero: print methods on standard output */
  374. XXchar *scriptf = SCRIPTFILE;    /* default script file */
  375. XXDATE bigbang;            /* a date, the very earliest possible */
  376. XXDATE endoftime;            /* a date, the very last possible */
  377.  
  378.  
  379. XXmain(argc, argv)
  380. XXint argc;
  381. XXchar **argv;
  382. XX{
  383. XX    int arg, i;
  384. XX    char *mfile = NULL;
  385. XX    DATE adate();
  386.  
  387. XX    bigbang = adate(0, 0);        /* init root dates */
  388. XX    endoftime = adate(~0, ~0);
  389.  
  390. XX    for(arg = 1; arg < argc; ++arg)
  391. XX        if(*argv[arg] == '-') switch(tolower(argv[arg][1]))
  392. XX        {
  393. XX           case 'f':
  394. XX            if(++arg >= argc)
  395. XX            {
  396. XX                fprintf(stderr, "-f needs filename argument.\n")
  397. XX;
  398. XX                return;
  399. XX            }
  400. XX            mfile = argv[arg];
  401. XX            break;
  402.  
  403. XX           case 'a':
  404. XX            obsolete = 1;
  405. XX            break;
  406.  
  407. XX           case 'n':
  408. XX            noscript = 1;
  409. XX            break;
  410.  
  411. XX           case 'd':
  412. XX            debug = 1;
  413. XX            break;
  414.  
  415. XX           case 'o':
  416. XX               scriptf = argv[arg] + 2;
  417. XX            break;
  418.  
  419. XX           default:
  420. XX            fprintf(stderr, "Unknown switch: %c\n", argv[arg][1]);
  421. XX            break;
  422. XX        } else if(modcount < MAXMODS)
  423. XX            modnames[modcount++] = argv[arg];
  424. XX        else
  425. XX        {
  426. XX            fprintf(stderr, "Too many module names.\n");
  427. XX            return;
  428. XX        }
  429.  
  430. XX    if(mfile != NULL)
  431. XX    {
  432. XX        if(fmake(mfile) == -1)
  433. XX            fprintf(stderr, "Cannot open makefile '%s'.\n", mfile);
  434. XX    } else {
  435. XX        for(i = 0; *mfiles[i]; ++i)
  436. XX            if(fmake(mfiles[i]) != -1) break;
  437. XX        if(!*mfiles[i])
  438. XX            fprintf(stderr, "Cannot open makefile.\n");
  439. XX    }
  440.  
  441. XX    if(debug) prtree();
  442. XX}
  443.  
  444.  
  445. XX/*
  446. XX * Construct dependency tree from the makefile 'fn'.
  447. XX * Figure out what has to be recompiled, and write a script file to do that.
  448. XX */
  449. XXfmake(fn)
  450. XXchar *fn;
  451. XX{
  452. XX    FILE *fp;
  453.  
  454. XX    if((fp = fopen(fn, "r")) == NULL) return -1;
  455.  
  456. XX    fparse(fp);
  457. XX    determ();
  458.  
  459. XX    fclose(fp);
  460. XX    return 0;
  461. XX}
  462.  
  463.  
  464. XX/*
  465. XX * Parse the input file, defining macros and building the dependency tree.
  466. XX */
  467. XXfparse(fp)
  468. XXFILE *fp;
  469. XX{
  470. XX    char ibuf[STRSIZ], ebuf[STRSIZ];
  471. XX    char *strp, *tok1, *tok2, *s;
  472. XX    FILENODE *lastf = NULL;
  473. XX    FILENODE *sf;
  474.  
  475. XX    for(;;)
  476. XX    {
  477. XX        if(fgets(ibuf, STRSIZ, fp) == NULL) break;
  478. XX        mexpand(ibuf, ebuf, STRSIZ, MACCHAR);
  479. XX        escape(ebuf, COMCHAR);
  480.  
  481. XX            /* clobber last newline in string */
  482. XX        s = ebuf + strlen(ebuf) - 1;
  483. XX        if(s >= ebuf && *s == '\n') *s = '\0';
  484.  
  485. XX        if(*ebuf == '\t')
  486. XX        {
  487. XX            addmeth(lastf, ebuf+1);
  488. XX            continue;
  489. XX        }
  490.  
  491. XX        strp = ebuf;
  492. XX        if((tok1 = token(&strp)) == NULL) continue;
  493. XX        if((tok2 = token(&strp)) != NULL)
  494. XX            if(!strcmp(tok2, DEFMAC))
  495. XX            {
  496. XX                if(*strp) defmac(tok1, strp);
  497. XX                else if(undefmac(tok1) < 0)
  498. XX                    fprintf(stderr,
  499. XX                      "Can't undefine macro '%s'\n", tok1);
  500. XX                continue;
  501. XX            }
  502. XX            else if(!strcmp(tok2, DEPEND))
  503. XX            {
  504. XX                addmeth(lastf, gmacro(AFTER));
  505.  
  506. XX                lastf = filenode(tok1);
  507. XX                if(firstf == NULL) firstf = lastf;
  508. XX                lastf->fmake = NULL;
  509.  
  510. XX                addmeth(lastf, gmacro(BEFORE));
  511.  
  512. XX                lastf->fflag |= ROOTP;
  513. XX                while((tok1 = token(&strp)) != NULL)
  514. XX                    addfile(lastf, tok1);
  515. XX                continue;
  516. XX            }
  517. XX            else addfile(lastf, tok2);
  518.  
  519. XX        do {
  520. XX            addfile(lastf, tok1);
  521. XX        } while((tok1 = token(&strp)) != NULL);
  522. XX    }
  523.  
  524. XX    addmeth(lastf, gmacro(AFTER));
  525. XX}
  526.  
  527.  
  528. XX/*
  529. XX * Determine sequence of recompiles from the creation dates.
  530. XX * If there is anything to recompile, then create a script file full of commands
  531. XX.
  532. XX */
  533. XXdeterm()
  534. XX{
  535. XX    FILENODE *f;
  536. XX    int i;
  537. XX    char *m;
  538.  
  539. XX    if(firstf == NULL)            /* empty tree */
  540. XX    {
  541. XX        printf("No changes.\n");
  542. XX        return;
  543. XX    }
  544.  
  545. XX    if(modcount == 0) examine(firstf, endoftime);
  546. XX    else for(i = 0; i < modcount; ++i)
  547. XX    {
  548. XX        if((f = gfile(modnames[i])) == NULL)
  549. XX        {
  550. XX            fprintf(stderr, "Can't find root '%s'.\n", modnames[i]);
  551. XX            continue;
  552. XX        }
  553.  
  554. XX        if(f->fflag & ROOTP == 0)
  555. XX        {
  556. XX            fprintf(stderr, "'%s' is not a root!\n", f->fname);
  557. XX            continue;
  558. XX        }
  559. XX        examine(f, endoftime);
  560. XX    }
  561.  
  562. XX    if(mkfp != NULL)
  563. XX    {
  564. XX        if((m = gmacro(DEINIT)) != NULL)
  565. XX        {
  566. XX            fputs(m, mkfp);
  567. XX            fputc('\n', mkfp);
  568. XX        }
  569. XX        fclose(mkfp);
  570. XX    } else printf("No changes.\n");
  571. XX}
  572.  
  573.  
  574. XX/*
  575. XX * Examine filenode 'fnd' and see if it has to be recompiled.
  576. XX * 'date' is the last-touched date of the node's father
  577. XX * (or 'endoftime' if its a root file.)
  578. XX * Root files with NO dependencies are assumed not to be up to date.
  579. XX */
  580. XXexamine(fnd, date)
  581. XXFILENODE *fnd;
  582. XXDATE date;
  583. XX{
  584. XX    int rebuildp = 0;
  585. XX    NODE *n;
  586.  
  587. XX    getdate(fnd);
  588. XX    if(fnd->fnode == NULL && fnd->fflag & ROOTP)
  589. XX        rebuildp = 1;
  590. XX    else for(n = fnd->fnode; n != NULL; n = n->nnext)
  591. XX        if(examine(n->nfile, fnd->fdate)) rebuildp = 1;
  592.  
  593. XX    if(rebuildp) recomp(fnd);
  594. XX    if(obsolete || laterdt(fnd->fdate, date) >= 0)
  595. XX        rebuildp = 1;
  596. XX    return rebuildp;
  597. XX}
  598.  
  599.  
  600. XX/*
  601. XX * Make sure a filenode gets recompiled.
  602. XX */
  603. XXrecomp(f)
  604. XXFILENODE *f;
  605. XX{
  606. XX    FILENODE *sf;
  607. XX    char *m;
  608.  
  609. XX    if(mkfp == NULL)
  610. XX    {
  611. XX        if(noscript) mkfp = stdout;
  612. XX        else if((mkfp = fopen(scriptf, "w")) == NULL)
  613. XX            fprintf(stderr, "Cannot create: '%s'\n", scriptf);
  614.  
  615. XX    if((m = gmacro(INIT)) != NULL)
  616. XX        {
  617. XX            fputs(m, mkfp);
  618. XX            fputc('\n', mkfp);
  619. XX        }
  620. XX    }
  621.  
  622. XX    if(f->fflag & REBUILT) return;
  623. XX    if(f->fmake != NULL) fputs(f->fmake, mkfp);
  624. XX    f->fflag |= REBUILT;
  625. XX}
  626.  
  627.  
  628. XX/*
  629. XX * Complain about being out of memory, and then die.
  630. XX */
  631. XXallerr() {
  632. XX    fprintf(stderr, "Can't alloc -- no space left (I give up!)\n");
  633. XX    exit(1);
  634. XX}
  635. @//E*O*F make.c//
  636. chmod u=rw,g=r,o= make.c
  637.  
  638. echo x - make.h
  639. sed 's/^XX//' > "make.h" <<'@//E*O*F make.h//'
  640. XX/* #define    VAXVMS    1 */        /* uncomment for VAX/VMS */
  641. XX/* #define    MSDOS    1 */        /* uncomment for MSDOS */
  642.  
  643. XX#ifdef VAXVMS
  644. XX#define ESCCHAR    `\\`        /* ok to use backslash on VMS */
  645. XX#endif
  646.  
  647. XX#ifdef MSDOS
  648. XX#define    ESCCHAR    '`'        /* since pathname char is backslash (yech) */
  649. XX#endif
  650.  
  651. XX#define    MACCHAR '#'        /* macro-definition char */
  652. XX#define    COMCHAR    '!'        /* comment char */
  653. XX#define    DEFMAC    "="        /* macro-definition token */
  654. XX#define    DEPEND    ":"        /* dependency-definition token */
  655.  
  656. XX#define    DEBUG    if(0)
  657. XX#define    STRSIZ    512
  658. XX#define    MAXMODS    50
  659.  
  660. XX/* file attributes */
  661. XX#define    REBUILT    0x01        /* file has been reconstructed */
  662. XX#define    ROOTP    0x02        /* file was named on left side of DEPEND */
  663.  
  664.  
  665. XXstruct date_str {
  666. XX    unsigned ds_low, ds_high;
  667. XX};
  668. XXtypedef struct date_str *DATE;
  669.  
  670.  
  671. XXstruct node {
  672. XX    struct filenode *nfile;    /* this node's file */
  673. XX    struct node *nnext;    /* the next node */
  674. XX};
  675. XXtypedef struct node NODE;
  676.  
  677.  
  678. XXstruct filenode {
  679. XX    char *fname;        /* the filename */
  680. XX    char *fmake;        /* remake string for file */
  681. XX    DATE fdate;        /* 32 bit last-modification date */
  682. XX    NODE *fnode;        /* files this file depends on */
  683. XX    char fflag;        /* magic flag bits */
  684. XX    struct filenode *fnext;    /* the next file */
  685. XX};
  686. XXtypedef struct filenode FILENODE;
  687.  
  688.  
  689. XXstruct macro {
  690. XX    char *mname;        /* the macro's name */
  691. XX    char *mvalue;        /* the macro's definition */
  692. XX    struct macro *mnext;    /* the next macro */
  693. XX};
  694. XXtypedef struct macro MACRO;
  695.  
  696.  
  697. XXextern MACRO *mroot;
  698. XXextern FILENODE *froot;
  699. XXextern DATE bigbang;        /* Far, far in the past */
  700. XXextern DATE endoftime;        /* Far, far in the future */
  701. XXchar *gmacro();
  702. XXFILENODE *filenode(), *gfile();
  703. XXchar *token();
  704. @//E*O*F make.h//
  705. chmod u=rw,g=r,o= make.h
  706.  
  707. echo x - make.man
  708. sed 's/^XX//' > "make.man" <<'@//E*O*F make.man//'
  709. XXMAKE(I)                3/10/84                    MAKE(I)
  710.  
  711.  
  712.  
  713. XXNAME
  714. XX    MAKE - maintain multiple source files (VAX/VMS and MSDOS 2.0)
  715.  
  716.  
  717. XXSYNOPSIS
  718. XX    MAKE [-N] [-A] [-F makefile] [name ...]
  719.  
  720.  
  721. XXDESCRIPTION
  722. XX    MAKE is a utility inspired by the Unix(tm) command of the same
  723. XX    name.  MAKE helps maintain programs that are constructed from
  724. XX    many files.  MAKE processes a "makefile", a file which describes
  725. XX    how to build a program from its source files, and produces a
  726. XX    script file containing the commands necessary to recompile the
  727. XX    program.
  728.  
  729. XX    Be careful: this MAKE is NOT compatible with Unix(tm) MAKE!
  730.  
  731. XX    The 'N' option causes MAKE to print out the steps it would follow
  732. XX    in order to rebuild the program.  The 'A' option tells MAKE to
  733. XX    assume that all files are obsolete, and that everything should be
  734. XX    recompiled.  The 'F' option, followed by a filename, can be used
  735. XX    to specify a makefile other than the default one.
  736.  
  737. XX    If no names are specified in the commandline, the first dependency
  738. XX    in the makefile is examined.  Otherwise, the specified root names
  739. XX    are brought up to date.
  740.  
  741. XX    The default makefiles are:
  742.  
  743. XX        for VAX/VMS:    MAKEFILE
  744. XX                [-]MAKEFILE
  745. XX                SYS$LOGIN:MAKEFILE
  746.  
  747. XX        for MSDOS:    MAKEFILE
  748. XX                ..\MAKEFILE
  749.  
  750. XX    If the first makefile cannot be found, MAKE attempts to use the
  751. XX    next one.  If no makefile is ever found, MAKE prints a diagnostic
  752. XX    and aborts.
  753.  
  754.  
  755.  
  756.  
  757.  
  758. XXTHE MAKEFILE
  759. XX    Comments begin with '!' and extend to the end of the line.  A
  760. XX    '!' (or almost any other character) may be escaped with the escape
  761. XX    character (backslash (\) on VMS, backquote (`) on MSDOS).  An escape
  762. XX    character may be typed by doubling it (\\ or ``).  The standard
  763. XX    Unix escape codes are recognized (\n, \r, \t, \b, \f, `n, `r, `t,
  764. XX    `b and `f).
  765.  
  766. XX    A makefile is a list of dependencies.  A dependency consists of
  767. XX    a root name, a colon, and zero or more names of dependent files.
  768. XX    (The colon MUST be preceeded by whitespace.)  For instance, in:
  769.  
  770. XX        make.exe : make.obj parsedir.obj file.obj macro.obj mk.h
  771.  
  772. XX    the file 'make.exe' depends on five other files.  A root name
  773. XX    with an empty dependency, as in:
  774.  
  775. XX        print :
  776.  
  777. XX    is assumed NEVER up to date, and will always be recompiled.
  778.  
  779. XX    The dependency list may be continued on successive lines:
  780.  
  781. XX        bigfile.exe : one.obj two.obj three.obj four.obj
  782. XX        five.obj six.obj gronk.obj freeple.obj scuzzy.lnk
  783. XX        frog.txt greeble.out
  784.  
  785. XX    Any number of 'method' lines may follow a dependency.  Method lines
  786. XX    begin with an ascii tab.  When a file is to be recompiled, MAKE
  787. XX    copies these method lines (minus the tab) to the script file.
  788. XX    For example, in:
  789.  
  790. XX        make.exe : make.obj parsedir.obj file.obj macro.obj mk.h
  791. XX            $link make, parsedir, file, macro
  792. XX            $write sys$output "Just another version of MAKE ..."
  793. XX            $purge
  794.  
  795. XX    the three lines following the dependency make up the method for
  796. XX    recompiling (or in this case, re-linking) the file 'make.exe'.
  797.  
  798. XX    If the macro "~INIT" is defined, its text will appear first in the
  799. XX    script file.  If the macro "~DEINIT" is defined, its text will
  800. XX    appear last in the script file.  By defining these two macros, it
  801. XX    is possible to configure the shell enviroment:
  802.  
  803. XX        ~INIT = $set term/nowrap\n$on error then goto err_handler
  804. XX        ~DEINIT = $set term/wrap\n$exit\$err_handler:\n
  805. XX        ~DEINIT = #(~DEINIT)$type err.log\n$exit
  806.  
  807. XX    will expand (in the script file) to:
  808.  
  809. XX        $set term/nowrap
  810. XX        $on error then goto err_handler
  811. XX        .
  812. XX        .
  813. XX        $set term/wrap
  814. XX        $exit
  815. XX        $err_handler:
  816. XX        $type err.log
  817. XX        $exit
  818.  
  819. XX    When a root's method is defined, the value of the macro "~BEFORE"
  820. XX    is prefixed to the method, and the value of the macro "~AFTER" is
  821. XX    appended to it.
  822.  
  823. XX    Frequently one wants to maintain more than one program with a single
  824. XX    makefile.  In this case, a "master dependency" can appear first in
  825. XX    the file:
  826.  
  827. XX        allOfMyToolsAndHorribleHacks : cat peek poke.exe grunge
  828. XX        cat : cat.exe
  829. XX        cat.exe : ....
  830. XX            (stuff for CAT.EXE)
  831. XX        peek : peek.exe
  832. XX        peek.exe : (stuff for PEEK.EXE)
  833. XX        poke.exe : (stuff for POKE.EXE)
  834. XX        grunge : grunge.com
  835. XX        grunge.com : (stuff for grung)
  836.  
  837. XX    In other words, make will bring everything up to date that is somehow
  838. XX    connected to the first dependency (its assumed that the incredibly
  839. XX    lengthy filename specified in this example won't actually exist).
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849. XXMACROS
  850. XX    A macro is defined by a line of the form (the '=' MUST be surrounded
  851. XX    by whitespace):
  852.  
  853. XX        <macro-name> = <macro-body>
  854.  
  855. XX    A macro may be deleted by assigning an empty value to it.  Macros
  856. XX    may be redefined, but old definitions stay around.  If a macro is
  857. XX    redefined, and the redefinition is later deleted, the first definition
  858. XX    will take effect:
  859.  
  860. XX        MAC = first            ! MAC = "first"
  861. XX        MAC = second            ! MAC = "second"
  862. XX        MAC = #(MAC) third        ! MAC = "second third"
  863. XX        MAC =                ! MAC = "second"
  864. XX        MAC =                ! MAC = "first"
  865. XX        MAC =                ! MAC has no definition
  866.  
  867. XX    A macro may be referenced in two ways:
  868.  
  869. XX            #<char>      or    #(macro-name)
  870.  
  871. XX    The first way only works if the macro's name is a single character.
  872. XX    If the macro's name is longer than one character, it must be
  873. XX    enclosed in parenthesis.  ['#' may be escaped by doubling it ("##".)]
  874. XX    For example, in:
  875.  
  876. XX        G = mk.h mk1.h
  877. XX        OBJS = make.obj file.obj parsedir.obj macro.obj
  878. XX        BOTH = #(OBJS) #G
  879. XX    
  880. XX        make.exe : #(OBJS) #G
  881. XX        make.exe : #(BOTH)
  882. XX        make.exe : mk.h mk1.h make.obj file.obj parsedir.obj macro.obj
  883. XX            $write sys$output "This is a number sign --> ##"
  884.  
  885. XX    after macro expansion, the three dependencies will appear identical
  886. XX    and the two '#'s in the last line will turn into one '#'.
  887.  
  888.  
  889.  
  890.  
  891.  
  892.  
  893.  
  894.  
  895.  
  896.  
  897. XXUNIX(tm) MAKE AND THIS ONE
  898. XX    They are NOT the same.  Do not expect Unix makefiles to work with
  899. XX    this MAKE, even if you change the pathnames.  There are some major
  900. XX    differences between this version and the standard Unix(tm) MAKE:
  901.  
  902. XX    1. The Unix(tm) comment character is '#', VAX/VMS's is '!'.
  903.  
  904. XX    2. The Unix(tm) macro-expansion character is '$'.  While this would
  905. XX       have been easy to leave the same, the '$' character is used so
  906. XX       often in VAX/VMS command-lines that I thought it best to change
  907. XX       it to '#'.
  908.  
  909. XX    3. Multiple root names are not allowed.  Unix(tm) MAKE accepts lines
  910. XX       of the form:
  911.  
  912. XX        name1 name2 : depend1 depend2
  913.  
  914. XX       but this one doesn't.
  915.  
  916. XX    4. There is no equivalent of double-colon ("::".)
  917.  
  918. XX    5. There is no equivalent of .SUFFIXES, or the corresponding special
  919. XX       macros.
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.  
  932.  
  933.  
  934.  
  935.  
  936.  
  937.  
  938.  
  939.  
  940.  
  941.  
  942.  
  943.  
  944.  
  945. XXSAMPLE MAKEFILE
  946. XX    !
  947. XX    ! VAX/VMS MAKE
  948. XX    ! Landon Dyer
  949. XX    !
  950. XX    H = make.h
  951. XX    FILES = #H, make.c, macro.c, token.c, parsedir.c, file.c
  952. XX    DOCUMENTATION = distr.mem make.man makefile. make.com
  953. XX    
  954. XX    make.exe : make.obj macro.obj token.obj parsedir.obj file.obj
  955. XX        $link make.obj, macro, token, parsedir, file
  956. XX        $purge
  957. XX    
  958. XX    make.obj : make.c #H
  959. XX        $cc make.c
  960. XX    
  961. XX    macro.obj : macro.c #H
  962. XX        $cc macro
  963. XX    
  964. XX    token.obj : token.c #H
  965. XX        $cc token
  966. XX    
  967. XX    parsedir.obj : parsedir.c #H
  968. XX        $cc parsedir
  969. XX    
  970. XX    file.obj : file.c
  971. XX        $cc file
  972. XX    
  973. XX    !
  974. XX    ! Print files associated with MAKE
  975. XX    !
  976. XX    print :
  977. XX        $print make.man, #(FILES), make.com, makefile.
  978. XX    
  979. XX    !
  980. XX    ! Type out source to MAKE
  981. XX    !
  982. XX    type :
  983. XX        $type #(FILES), make.com, makefile.
  984. XX    
  985. XX    !
  986. XX    ! Make backup of source files.
  987. XX    !
  988. XX    BACKUP = [.bak]
  989. XX    backup :
  990. XX        $copy #(FILES) #(BACKUP)
  991. XX        $copy make.man, make.com, makefile. #(BACKUP)
  992. XX    
  993. XX    !
  994. XX    ! Collect MAKE into a distribution file.
  995. XX    !
  996. XX    collect :
  997. XX        $collect collect distr.mem make.man makefile make.com make.h -
  998. XX            make.c macro.c token.c parsedir.c file.c
  999.  
  1000.  
  1001. XXAUTHOR
  1002. XX    Landon Dyer            G.DYER@SU-SCORE.ARPA
  1003. XX    175 Calvert Dr. #F-211        BASHFL::DYER (Atari Coinop)
  1004. XX    Cupertino, CA 95014
  1005. @//E*O*F make.man//
  1006. chmod u=rw,g=r,o= make.man
  1007.  
  1008. echo x - makefile
  1009. sed 's/^XX//' > "makefile" <<'@//E*O*F makefile//'
  1010. XX!
  1011. XX! MSDOS Make utility
  1012. XX! (compile with Lattice C version 2.1)
  1013. XX!
  1014.  
  1015. XXCLIB = e:\lc\s\lc
  1016. XXCOBJ = e:\lc\s\c
  1017. XXLCS = lc -ms -ie:\lc\
  1018. XXH = make.h
  1019. XXFILES = #H make.c macro.c token.c parsedir.c file.c osdate.asm
  1020. XXDOCUMENTATION = readme make.man makefile
  1021.  
  1022. XXxmake.exe : make.obj macro.obj token.obj parsedir.obj file.obj osdate.obj
  1023. XX    link #(COBJ) make macro token parsedir file osdate,xmake,nul,#(CLIB)
  1024.  
  1025. XXmake.obj : make.c #H
  1026. XX    #(LCS) make
  1027.  
  1028. XXmacro.obj : macro.c #H
  1029. XX    #(LCS) macro
  1030.  
  1031. XXtoken.obj : token.c #H
  1032. XX    #(LCS) token
  1033.  
  1034. XXparsedir.obj : parsedir.c #H
  1035. XX    #(LCS) parsedir
  1036.  
  1037. XXfile.obj : file.c
  1038. XX    #(LCS) file
  1039.  
  1040. XXosdate.obj : osdate.asm
  1041. XX    masm osdate;
  1042.  
  1043. XX!
  1044. XX! Print files associated with MAKE
  1045. XX!
  1046. XXprint :
  1047. XX    print make.man #(FILES) makefile
  1048.  
  1049.  
  1050. XX!
  1051. XX! collect source and documentation files
  1052. XX!
  1053. XXcollect :
  1054. XX    collect -o make.col @make.lis
  1055.  
  1056.  
  1057. XX!
  1058. XX! copy to distribution disk (on A:)
  1059. XX!
  1060. XXdistribution :
  1061. XX    copy readme a:
  1062. XX    copy make.man a:
  1063. XX    copy makefile a:
  1064. XX    copy make.bat a:
  1065. XX    copy make.c a:
  1066. XX    copy macro.c a:
  1067. XX    copy token.c a:
  1068. XX    copy parsedir.c a:
  1069. XX    copy file.c a:
  1070. XX    copy osdate.asm a:
  1071. XX    copy cmake.bat a:
  1072. XX    copy make.lis a:
  1073. XX    copy xmake.exe a:
  1074. @//E*O*F makefile//
  1075. chmod u=rw,g=r,o= makefile
  1076.  
  1077. echo x - osdate.asm
  1078. sed 's/^XX//' > "osdate.asm" <<'@//E*O*F osdate.asm//'
  1079. XXdos    =    21h
  1080.  
  1081. XXarg1    =    4            ; lattice argument indexes
  1082. XXarg2    =    arg1+2
  1083. XXarg3    =    arg2+2
  1084.  
  1085. XXpgroup    group    prog
  1086. XXprog    segment byte public 'prog'
  1087. XX    public    osdate
  1088. XX    assume    cs:pgroup
  1089.  
  1090. XX;
  1091. XX;------
  1092. XX; OSDATE - return file's creation-date (called from Lattice), or -1
  1093. XX;       if can't find the file.
  1094. XX; Synopsis:
  1095. XX;        int osdate(filename, time1, time2)
  1096. XX;            char *filename;
  1097. XX;            int *time1, *time2;
  1098. XX;
  1099. XXosdate proc near
  1100. XX    push    bp
  1101. XX    mov    bp,sp
  1102.  
  1103. XX;--- Open the file
  1104. XX    mov    dx,[bp+arg1]
  1105. XX    xor    al,al
  1106. XX    mov    ah,3dh
  1107. XX    int    dos
  1108. XX    jc    osd$err            ; can't, so complain
  1109.  
  1110. XX;--- Get file's creation date and time
  1111. XX    mov    bx,ax            ; get handle's date info
  1112. XX    xor    al,al
  1113. XX    mov    ah,57h
  1114. XX    int    dos
  1115. XX    jc    osd$cls            ; "can't happen" (but close it)
  1116.  
  1117. XX;--- Install date/time info into caller's variables
  1118. XX    mov    si,[bp+arg2]        ; *arg2 = time (least significant)
  1119. XX    mov    [si],cx
  1120. XX    mov    si,[bp+arg3]        ; *arg3 = date (most significant)
  1121. XX    mov    [si],dx
  1122.  
  1123. XX;--- Close file & return (ok)
  1124. XX    mov    ah,3eh
  1125. XX    int    dos
  1126. XX    xor    ax,ax
  1127. XX    pop    bp
  1128. XX    ret
  1129.  
  1130. XX;--- Close file & return error condition
  1131. XXosd$cls:
  1132. XX    mov    ah,3eh
  1133. XX    int    dos
  1134. XXosd$err:
  1135. XX    mov    ax,-1
  1136. XX    pop    bp
  1137. XX    ret
  1138. XXosdate endp
  1139.  
  1140. XXprog    ends
  1141. XX    end
  1142. @//E*O*F osdate.asm//
  1143. chmod u=rw,g=r,o= osdate.asm
  1144.  
  1145. echo x - parsedir.c
  1146. sed 's/^XX//' > "parsedir.c" <<'@//E*O*F parsedir.c//'
  1147. XX#include <stdio.h>
  1148. XX#include "make.h"
  1149. XX#ifdef VAXVMS
  1150. XX#include <rms.h>
  1151. XX#endif
  1152.  
  1153.  
  1154. XX/*
  1155. XX * Get a file's creation date.
  1156. XX */
  1157. XXint getdate(f)
  1158. XXFILENODE *f;
  1159. XX{
  1160. XX    if(f->fdate != NULL || filedate(f) != -1) return;
  1161.  
  1162. XX    if(f->fflag & ROOTP == 0)
  1163. XX    {
  1164. XX        fprintf(stderr, "Can't get date for file '%s'\n", f->fname);
  1165. XX        f->fdate = endoftime;
  1166. XX    } else f->fdate = bigbang;
  1167. XX    return;
  1168. XX}
  1169.  
  1170.  
  1171. XX#ifdef VAXVMS
  1172. XX/*
  1173. XX * filedate - return file's creation date (VAX/VMS only.)
  1174. XX * Returns -1 if file cannot be found, 0 if succesful.
  1175. XX */
  1176. XXfiledate(fnd)
  1177. XXFILENODE *fnd;
  1178. XX{
  1179. XX    unsigned *datetime;
  1180. XX    DATE adate();
  1181. XX    struct FAB *fptr;
  1182. XX    struct XABDAT *dptr;
  1183.  
  1184. XX    fptr = malloc(sizeof(struct FAB));    /* allocate FAB and XABDAT */
  1185. XX    dptr = malloc(sizeof(struct XABDAT));
  1186. XX    if(fptr == NULL || dptr == NULL) allerr();
  1187. XX    *fptr = cc$rms_fab;            /* initialize FAB and XABDAT */
  1188. XX    *dptr = cc$rms_xabdat;
  1189. XX    fptr->fab$l_xab = (char *) dptr;    /* FAB -> XABDAT */
  1190.  
  1191. XX    fptr->fab$l_fna = fnd->fname;        /* setup filename */
  1192. XX    fptr->fab$b_fns = strlen(fnd->fname);
  1193.  
  1194. XX    if(sys$open(fptr) != RMS$_NORMAL ||    /* open the file */
  1195. XX       sys$display(fptr) != RMS$_NORMAL)    /* get XABDAT info */
  1196. XX        return -1;
  1197.  
  1198. XX    datetime = &(dptr->xab$q_cdt);        /* record 64-bit date */
  1199. XX    fnd->fdate = adate(datetime[0], datetime[1]);
  1200.  
  1201. XX    sys$close(fptr);            /* close the file */
  1202.  
  1203. XX    free(dptr);                /* clean up and return */
  1204. XX    free(fptr);
  1205. XX    return 0;
  1206. XX}
  1207. XX#endif
  1208.  
  1209.  
  1210. XX#ifdef MSDOS
  1211. XX/*
  1212. XX * filedate - return file's creation date (MSDOS only.)
  1213. XX * Returns -1 if file cannot be found, 0 if successful
  1214. XX */
  1215. XXfiledate(fnd)
  1216. XXFILENODE *fnd;
  1217. XX{
  1218. XX    unsigned date, time;
  1219. XX    DATE adate();
  1220.  
  1221. XX    if(osdate(fnd->fname, &time, &date) == -1) return -1;
  1222. XX    fnd->fdate = adate(time, date);
  1223. XX}
  1224. XX#endif
  1225.  
  1226.  
  1227. XX/*
  1228. XX * laterdt - compare two dates.
  1229. XX * Return -1, 0 or 1 if date1 < date2, date1 == date2, or date1 > date2
  1230. XX */
  1231. XXlaterdt(date1, date2)
  1232. XXDATE date1, date2;
  1233. XX{
  1234. XX    if(date1->ds_high > date2->ds_high ||
  1235. XX       (date1->ds_high >= date2->ds_high &&
  1236. XX        date1->ds_low > date2->ds_low)) return 1;
  1237. XX    else if(date1->ds_high == date2->ds_high &&
  1238. XX       date1->ds_low == date2->ds_low) return 0;
  1239. XX    else return -1;
  1240. XX}
  1241.  
  1242.  
  1243. XX/*
  1244. XX * adate - allocate a date with the given time
  1245. XX */
  1246. XXDATE adate(time1, time2)
  1247. XXunsigned time1, time2;
  1248. XX{
  1249. XX    DATE d;
  1250.  
  1251. XX    if((d = (DATE)malloc(sizeof(struct date_str))) == NULL) allerr();
  1252. XX    d->ds_low = time1;
  1253. XX    d->ds_high = time2;
  1254. XX    return d;
  1255.  
  1256. XX}
  1257. @//E*O*F parsedir.c//
  1258. chmod u=rw,g=r,o= parsedir.c
  1259.  
  1260. echo x - readme
  1261. sed 's/^XX//' > "readme" <<'@//E*O*F readme//'
  1262.  
  1263. XXLast month I wrote a version of the Unix(tm) utility MAKE.  It runs under
  1264. XXVAX/VMS and MSDOS 2.0.  I am placing it in the public domain, and it is yours
  1265. XXfor the asking.  You may copy it, or give it away.  You can make any changes
  1266. XXyou like to it.  All I ask is that you DO NOT TRY TO SELL IT.
  1267.  
  1268. XXAnyway, there is now a MAKE for MSDOS.  It is free, and it works pretty well.
  1269. XXI'm giving it away because it might do the world some good.  Who knows?
  1270.  
  1271. XXCaveat: this version of MAKE is NOT compatible with the Unix(tm) version.
  1272. XXSome differences are explained in the documentation.  Most of the problem stems
  1273. XXfrom the fact that I've never had a chance to use the original version of MAKE,
  1274. XXand the documentation I've seen on it has been poor.  My idea of what a make
  1275. XXprogram should do is almost certainly different from what you Unix(tm) hackers
  1276. XXare used to.  Well, hell -- the software is worth what you paid for it.  Have
  1277. XXfun.
  1278.  
  1279. XXIn order to get MAKE running on your system, you need to:
  1280.  
  1281. XX    1.  Read the documentation file MAKE.MAN.  (Yes, read the
  1282. XX        directions.)
  1283.  
  1284. XX    2.  Edit the file MAKE.H to represent your system (VAX/VMS or
  1285. XX        MSDOS 2.0.)
  1286.  
  1287. XX    3.  Recompile the source code by following the script file
  1288. XX        CMAKE.COM (for VAX/VMS) or CMAKE.BAT (for MSDOS 2.0.)
  1289.  
  1290. XX        VAX/VMS requires the DEC C compiler; MSDOS 2.0 requires
  1291. XX        Lattice C (or another C compiler of comparable quality)
  1292. XX        and the Macro Assembler.
  1293.  
  1294. XX    4.  Test out MAKE by running it on itself.  (Make a backup
  1295. XX        first!)
  1296.  
  1297.  
  1298.  
  1299. XX            Good luck,
  1300.  
  1301. XX            Landon Dyer (G.DYER @ SU-SCORE)
  1302. @//E*O*F readme//
  1303. chmod u=rw,g=r,o= readme
  1304.  
  1305. echo x - token.c
  1306. sed 's/^XX//' > "token.c" <<'@//E*O*F token.c//'
  1307. XX#include <stdio.h>
  1308. XX#include <ctype.h>
  1309. XX#include "make.h"
  1310.  
  1311. XX/*
  1312. XX * Get next token from the string.  Return a pointer to it, or NULL.
  1313. XX * Adjust pointer to point to next part of string.
  1314. XX * The string is modified.
  1315. XX * A token consists of any number of non-white characters.
  1316. XX */
  1317. XXchar *token(strpp)
  1318. XXchar **strpp;
  1319. XX{
  1320. XX    char *s, *beg;
  1321.  
  1322. XX    stripwh(strpp);
  1323. XX    if(!**strpp) return NULL;
  1324.  
  1325. XX    beg = s = *strpp;
  1326. XX    while(*s && !isspace(*s)) ++s;
  1327. XX    if(*s) *s++ = '\0';
  1328. XX    *strpp = s;
  1329. XX    return beg;
  1330. XX}
  1331.  
  1332.  
  1333. XX/*
  1334. XX * Parse character escape-sequences in a line of text.
  1335. XX *    <EscChar><EscChar> = <EscChar>
  1336. XX *    <EscChar>n = newline, and so on
  1337. XX *    <EscChar><char> = <char>
  1338. XX * The string is truncated at the first non-escaped occurance of 'comchar'.
  1339. XX */
  1340. XXescape(str, comchar)
  1341. XXchar *str, comchar;
  1342. XX{
  1343. XX    char *d, c;
  1344.  
  1345. XX    for(d = str; *str && *str != comchar; ++str)
  1346. XX        if(*str == ESCCHAR && *(str + 1)) switch((c = *++str))
  1347. XX        {
  1348. XX           case ESCCHAR:
  1349. XX            *d++ = ESCCHAR;
  1350. XX            break;
  1351.  
  1352. XX           case 'n':
  1353. XX            *d++ = '\n';
  1354. XX            break;
  1355.  
  1356. XX           case 'r':
  1357. XX            *d++ = '\r';
  1358. XX            break;
  1359.  
  1360. XX           case 't':
  1361. XX            *d++ = '\t';
  1362. XX            break;
  1363.  
  1364. XX           case 'b':
  1365. XX            *d++ = '\b';
  1366. XX            break;
  1367.  
  1368. XX           case 'f':
  1369. XX            *d++ = '\f';
  1370. XX            break;
  1371.  
  1372. XX           default:
  1373. XX            *d++ = c;
  1374. XX            break;
  1375. XX        } else *d++ = *str;
  1376.  
  1377. XX    *d++ = 0;
  1378. XX}
  1379.  
  1380.  
  1381. XXstripwh(strpp)
  1382. XXchar **strpp;
  1383. XX{
  1384. XX    char *s;
  1385.  
  1386. XX    s = *strpp;
  1387. XX    while(isspace(*s)) ++s;
  1388. XX    return (*strpp = s);
  1389. XX}
  1390. @//E*O*F token.c//
  1391. chmod u=rw,g=r,o= token.c
  1392.  
  1393. echo Inspecting for damage in transit...
  1394. temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
  1395. trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
  1396. cat > $temp <<\!!!
  1397.       7     30    193 cmake.bat
  1398.     141    380   2556 file.c
  1399.     125    341   2263 macro.c
  1400.       4     21    116 make.bat
  1401.     315    920   6271 make.c
  1402.      64    263   1576 make.h
  1403.     296   1146   7304 make.man
  1404.      64    169   1070 makefile
  1405.      63    180   1058 osdate.asm
  1406.     110    336   2258 parsedir.c
  1407.      40    272   1535 readme
  1408.      83    211   1309 token.c
  1409.    1312   4269  27509 total
  1410. !!!
  1411. wc  cmake.bat file.c macro.c make.bat make.c make.h make.man makefile osdate.asm parsedir.c readme token.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
  1412. if test -s $dtemp
  1413. then echo "Ouch [diff of wc output]:" ; cat $dtemp
  1414. else echo "No problems found."
  1415. fi
  1416. exit 0
  1417.  
  1418.  
  1419.  
  1420.